<?php

namespace App\Models\Train\TrainOrderRefund\Refunds;

use App\Models\Task\SnapTasks\SnapTask;
use App\Models\Train\TrainOrders\TrainOrder;
use App\Models\Trip\OrderPay\Repositories\Interfaces\OrderPayRepositoryInterface;
use App\Models\Trip\OrderPay\SnapTaskEditPay;
use App\Models\Trip\TripOrderRefund\RefundDetail;
use App\Models\Trip\TripOrderRefund\Refunds\dealRefundInterface;
use App\Models\Trip\TripOrderRefund\TripOrderRefund;
use Exception;
use Illuminate\Support\Facades\Log;
use JetBrains\PhpStorm\ArrayShape;

class dealNoTicketEditTaskRefund implements dealRefundInterface
{

    private SnapTask        $task;
    private TrainOrder      $order_info;
    private TripOrderRefund $refund_model;
    private string          $log_key;
    private array           $refundInfos;
    private array           $refund_datas;
    private int|float       $total_price;
    private bool            $has_alone_pay_record;

    public function __construct(SnapTask $task, TrainOrder $order_info)
    {
        $this->task                 = $task;
        $this->order_info           = $order_info;
        $this->refund_model         = new TripOrderRefund();
        $this->log_key              = "编辑任务需支付的退款:task_id-{$task->getTaskId()},order_sn-{$order_info->getOrderSn()}";
        $this->refundInfos          = [];
        $this->refund_datas         = [];
        $this->total_price          = 0;
        $this->has_alone_pay_record = false;
        $this->dealRefundData();
    }

    private function dealRefundData()
    {
        // 是否存在编辑支付
        $edit_pay         = new SnapTaskEditPay();
        $edit_pays        = $edit_pay->listByTaskAndTrainOrder($this->task, $this->order_info);
        $edit_need_refund = [];
        $payRepo          = app(OrderPayRepositoryInterface::class);
        $total_price      = 0;
        foreach ($edit_pays as $edit_pay) {
            $pay_sn        = $edit_pay->getPaySn();
            $edit_pay_info = $payRepo->findOneByPaySn($pay_sn);
            if (!$edit_pay_info) {
                continue;
            }
            $this->has_alone_pay_record = true;
            $total_price                += $edit_pay_info->getPayAmount();
            // 验证是否退过
            $refund_sn        = "R".$edit_pay_info->getPaySn();
            $edit_refund_info = $this->refund_model->whereOutRefundNo($refund_sn)->first();
            if ($edit_refund_info) {
                // 如果已存在的 退款未成功,则加入重试列表
                Log::info("{$this->log_key}:升级支付已有退款记录,refund_sn:{$refund_sn}");
                if (!$edit_refund_info->isRefundedSuccess()) {
                    $this->refundInfos[] = $edit_refund_info;
                }
                continue;
            }
            $pay_success = false;
            if ($edit_pay_info->isPaySuccess()) {
                $pay_success = true;
            } else {
                // 通过支付反向查询
                try {
                    $pay_success = $edit_pay_info->isPayResultDataSuccess();
                } catch (Exception $exception) {
                    Log::error("{$this->log_key},任务取消,退款验证曾发起的支付结果,{$exception->getMessage()}");
                }
                Log::info("{$this->log_key},反查支付 pay_sn:{$edit_pay_info->getPaySn()},当前状态为已支付");
            }
            if ($pay_success) {
                // TODO 这里考虑 资金明细是否 落明细 如果落 之前业务的退款需要重构 ,明细显示也需要处理
                $details                   = [
                    [
                        "user_id"      => $this->order_info->getUserId(),
                        "refund_sn"    => $refund_sn,
                        "order_sn"     => $this->order_info->getOrderSn(),
                        "out_trade_no" => $edit_pay_info->getPaySn(),
                        "type"         => RefundDetail::TASK_EDIT_DIFF_FEE_REFUND,
                        "name"         => RefundDetail::getTypeDesc(RefundDetail::TASK_EDIT_DIFF_FEE_REFUND),
                        "amount"       => 0,
                        "count"        => 0,
                    ],
                ];
                $edit_need_refund[$pay_sn] = [
                    "user_id"         => $this->order_info->getUserId(),
                    "refund_sn"       => $refund_sn,
                    "out_refund_no"   => $refund_sn,
                    "out_trade_no"    => $edit_pay_info->getPaySn(),
                    "origin_order_sn" => $this->order_info->getOriginOrderSn(),
                    "order_sn"        => $this->order_info->getOrderSn(),
                    "ticket_price"    => 0,
                    "refund_amount"   => $edit_pay_info->getPayAmount(),
                    "pay_amount"      => $edit_pay_info->getPayAmount(),
                    "has_ticket"      => $this->refund_model::REFUND_NO_TICKET,
                    "refund_state"    => $this->refund_model::REFUND_STATE_REFUNDING, // 出票失败需要立即退款
                    "title"           => "无票退款-编辑任务",
                    "refund_type"     => $this->refund_model::REFUND_TYPE_NO_TICKET,
                    "trip_type"       => $this->order_info->getTripType(),
                    "details"         => $details,
                ];
            }
        }
        $this->total_price  = $total_price;
        $this->refund_datas = array_values($edit_need_refund);
    }

    public function getTotalPrice(): float|int
    {
        return $this->total_price;
    }

    #[ArrayShape([
        TripOrderRefund::class,
    ])] public function getNeedRefundInfos(): array
    {
        return $this->refundInfos;
    }

    public function getNewRefundData(): array
    {
        return $this->refund_datas;
    }

    public function hasAlonePayRecord(): bool
    {
        return $this->has_alone_pay_record;
    }
}